package com.mapflow.util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.i18n.LocaleContextHolder;

import com.mapflow.constans.Constants;

/**
 * Date Utility Class used to convert Strings to Dates and Timestamps
 * 
 * @author <a href="mailto:matt@raibledesigns.com">Matt Raible</a> Modified by <a
 *         href="mailto:dan@getrolling.com">Dan Kibler </a> to correct time pattern. Minutes should
 *         be mm not MM (MM is month).
 */
public final class DateUtil {

  private static Log log = LogFactory.getLog(DateUtil.class);
  private static final String TIME_PATTERN = "HH:mm";

  /**
   * This method generates a string representation of a date based on the System Property
   * 'dateFormat' in the format you specify on input
   * 
   * @param aDate
   *          A date to convert
   * @return a string representation of the date
   */
  public static String convertDateToString(final Date aDate) {
    return getDateTime(getDatePattern(), aDate);
  }

  /**
   * This method converts a String to a date using the datePattern
   * 
   * @param strDate
   *          the date to convert (in format MM/dd/yyyy)
   * @return a date object
   * @throws ParseException
   *           when String doesn't match the expected format
   */
  public static Date convertStringToDate(final String strDate) throws ParseException {
    return convertStringToDate(getDatePattern(), strDate);
  }

  /**
   * This method generates a string representation of a date/time in the format you specify on input
   * 
   * @param aMask
   *          the date pattern the string is in
   * @param strDate
   *          a string representation of a date
   * @return a converted Date object
   * @throws ParseException
   *           when String doesn't match the expected format
   * @see java.text.SimpleDateFormat
   */
  public static Date convertStringToDate(final String aMask, final String strDate)
    throws ParseException {
    SimpleDateFormat df;
    Date date;
    df = new SimpleDateFormat(aMask);

    if (log.isDebugEnabled()) {
      log.debug("converting '" + strDate + "' to date with mask '" + aMask + "'");
    }

    try {
      date = df.parse(strDate);
    }
    catch (final ParseException pe) {
      // log.error("ParseException: " + pe);
      throw new ParseException(pe.getMessage(), pe.getErrorOffset());
    }

    return (date);
  }

  /**
   * This method attempts to convert an Oracle-formatted date in the form dd-MMM-yyyy to mm/dd/yyyy.
   * 
   * @param aDate
   *          date from database as a string
   * @return formatted string for the ui
   */
  public static String getDate(final Date aDate) {
    SimpleDateFormat df;
    String returnValue = "";

    if (aDate != null) {
      df = new SimpleDateFormat(getDatePattern());
      returnValue = df.format(aDate);
    }

    return (returnValue);
  }

  /**
   * Return default datePattern (MM/dd/yyyy)
   * 
   * @return a string representing the date pattern on the UI
   */
  public static String getDatePattern() {
    final Locale locale = LocaleContextHolder.getLocale();
    String defaultDatePattern;
    try {
      defaultDatePattern =
        ResourceBundle.getBundle(Constants.BUNDLE_KEY, locale).getString("date.format");
    }
    catch (final MissingResourceException mse) {
      defaultDatePattern = "MM/dd/yyyy";
    }

    return defaultDatePattern;
  }

  /**
   * This method generates a string representation of a date's date/time in the format you specify
   * on input
   * 
   * @param aMask
   *          the date pattern the string is in
   * @param aDate
   *          a date object
   * @return a formatted string representation of the date
   * @see java.text.SimpleDateFormat
   */
  public static String getDateTime(final String aMask, final Date aDate) {
    SimpleDateFormat df = null;
    String returnValue = "";

    if (aDate == null) {
      log.warn("aDate is null!");
    }
    else {
      df = new SimpleDateFormat(aMask);
      returnValue = df.format(aDate);
    }

    return (returnValue);
  }

  public static String getDateTimePattern() {
    return DateUtil.getDatePattern() + " HH:mm:ss.S";
  }

  /**
   * This method returns the current date time in the format: MM/dd/yyyy HH:MM a
   * 
   * @param theTime
   *          the current time
   * @return the current date/time
   */
  public static String getTimeNow(final Date theTime) {
    return getDateTime(TIME_PATTERN, theTime);
  }

  /**
   * This method returns the current date in the format: MM/dd/yyyy
   * 
   * @return the current date
   * @throws ParseException
   *           when String doesn't match the expected format
   */
  public static Calendar getToday() throws ParseException {
    final Date today = new Date();
    final SimpleDateFormat df = new SimpleDateFormat(getDatePattern());

    // This seems like quite a hack (date -> string -> date),
    // but it works ;-)
    final String todayAsString = df.format(today);
    final Calendar cal = new GregorianCalendar();
    cal.setTime(convertStringToDate(todayAsString));

    return cal;
  }

  /**
   * Checkstyle rule: utility classes should not have public constructor
   */
  private DateUtil() {
  }
}
